package com.metadata_system.common.service;


import com.metadata_system.common.db.entity.AuthReflushToken;
import com.metadata_system.common.db.entity.User;
import com.metadata_system.common.db.mapper.UserMapper;
import com.metadata_system.common.dto.ApiResult;
import com.metadata_system.common.dto.JwtToken;
import com.metadata_system.common.http.request_dto.LoginUserRequest;
import com.metadata_system.common.http.request_dto.UserLoginRequest;
import com.metadata_system.common.http.response_dto.TokenResponse;
import com.metadata_system.common.utils.RegexUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

/**
 * @author safi
 * @date 2019年10月9日20:30:57
 */
@Service
@Slf4j
public class UserService{
    public static String DefaultPassword="pvalVE10AXypJcyFTssP4vzWm";

    @Value("${metadata-system.login-sign-device:true}")
    private boolean loginSignDevice = true;

    @Autowired(required = false)
    UserMapper userMapper;

    @Autowired
    UserLoginLogService userLoginLogService;
    @Autowired
    AuthTokenService authTokenService;

    @Autowired
    AuthReflushTokenService authReflushTokenService;

    @Autowired
    AuthTokenRepo authTokenRepo;

    @Autowired
    PasswordEncoder passwordEncoder;                // 密码校验器

    @Autowired
    LoginUserRequest loginUserRequest;

    public ApiResult login(UserLoginRequest request) {
        if (StringUtils.isBlank(request.getPlatform())){
            return ApiResult.error("设备平台(PC/H5/Android/iOS) 不能为空");
        }
        if (StringUtils.isBlank(request.getDeviceId())){
            return ApiResult.error("设备ID 不能为空");
        }
        // 1.检查用户名格式
        Integer params=0;
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        if (!RegexUtils.checkUsername(request.getUsername())) {
            ApiResult.error("用户名 格式错误");
        }
        // 2.检查用户名-是否存在
        criteria.andEqualTo("username", request.getUsername());
        if (this.userMapper.selectCountByExample(example)>1){
            log.info("当前用户大于2个: username: {},params: {}",request.getUsername(),params);
            return ApiResult.error("用户数据错误");
        }
        User user = this.userMapper.selectOneByExample(example);
        if (user == null) {
            return ApiResult.error("用户名 信息不存在-1");
        }
        if (user.getStatus().equals(0)) {
            return ApiResult.error("用户名 账号未开启");
        }
        if (user.getStatus().equals(2)){
            return ApiResult.error("当前账号 已经锁定");
        }
        if(user.getIsLogicToolAccess()==1){
            return ApiResult.error("当前逻辑图工具账号 不允许登录");
        }
        request.setUserId(user.getId());

        // 3.用户密码错误次数
        ApiResult result = this.userLoginLogService.checkErrorNums(request,user.getUnLockLoginTime());
        if (result.getCode() > 0) {
            return result;
        }

        // 4.检查用户密码是否正确
        if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
            // log.info("密码是: "+passwordEncoder.encode("a123456"));
            // 增加-登录错误日志
            request.setStatus(0);
            this.userLoginLogService.add(request);
            return ApiResult.error("用户名密码 错误");
        }

//        if (request.getUserType().equals("SysUser")){
//            request.setParams(this.systemUserMapper.getIdByUsername(request.getUsername()).toString());
//        }

        request.setRole(user.getRole());
        request.setAvatar(user.getAvatar());
        request.setName(user.getName());


        // 5.执行登录
        return ApiResult.success(this.execLogin(request));
    }




    /**
     * 执行登录操作
     *
     * @param request username=>用户名   userType=>用户类型: member.会员  sysUser.系统管理员    deviceId=>设备ID
     */
    public TokenResponse execLogin(UserLoginRequest request) {
        // 1.是否-单设备登录 (是=>清空当前【账号】token)
/*        if (this.loginSignDevice) {
            //
        }*/

        // 2.清空当前【设备ID】token
        this.authTokenRepo.clear(request.getPlatform(),request.getUserId());
        // 发送给其他用户检查token
//        this.commonSocketService.sendMessageToMore("CheckToken",request.getUserType(),Integer.valueOf(request.getParams()),"{}");

        // 3.创建,生成,返回: tokenID,reflushTokenID,JWT-token,JWT-reflushToken
        TokenResponse tokenResponse = this.authTokenService.generate(request);
        // 4.增加-登录成功日志
        request.setStatus(1);
        this.userLoginLogService.add(request);
        tokenResponse.setUsername(request.getUsername());
        tokenResponse.setAvatar(request.getAvatar());
        tokenResponse.setName(request.getName());
        tokenResponse.setRole(request.getRole());
        return tokenResponse;
    }


    // 退出登录

    public ApiResult loginOut(LoginUserRequest userTokenRequest) {
        // 清空当前【设备ID】token
        this.authTokenRepo.clear(userTokenRequest.getPlatform(),userTokenRequest.getUserId());
        return ApiResult.success("退出成功");
    }

    // 刷新 token

    public ApiResult reflushToken(LoginUserRequest userTokenRequest, String reflushToken) {
        // 1.当前 reflushToken 是否有效(token有效性已经通过aop判断了),返回的是: reflushTokenID
        AuthReflushToken authReflushToken = this.authReflushTokenService.checkToken(userTokenRequest, reflushToken);
        if (authReflushToken == null) {
            return ApiResult.error("token 已经失效");
        }
        JwtToken jwtToken = this.loginUserRequest.getTokenUser();
        // 2.【reflushToken 的 tokenId 】必须与 【请求 jwtToken 的 tokenId】 相同
        if (!jwtToken.getTokenId().equals(authReflushToken.getTokenId())) {
            return ApiResult.error("刷新token不匹配, jwtToken-token_id:{}  authReflushToken-token_id: {}");
        }
        UserLoginRequest userLoginRequest = UserLoginRequest.builder()
                .deviceId(userTokenRequest.getDeviceId())
                .role(jwtToken.getRole())
                .username(jwtToken.getUsername())
                .build();
        // 3.清空当前 reflushToken,token 根据 token_id
//        this.authTokenRepo.clear(AuthToken.builder()
//                .userType(jwtToken.getUserType())
//                .tokenId(authReflushToken.getTokenId())
//                .build()
//        );
        // 3.创建,生成,返回: tokenID,reflushTokenID,JWT-token,JWT-reflushToken
        TokenResponse tokenResponse = this.authTokenService.generate(userLoginRequest);
        return ApiResult.success(tokenResponse);
    }


    public ApiResult changePassword(Integer userId, String oldPassword, String password) {
        User user = this.userMapper.selectByPrimaryKey(userId);
        // 1.格式校验
        if (oldPassword.length() < 6) {
            return ApiResult.error("旧密码 长度不能少于6位");
        }
        if (password.length() < 6) {
            return ApiResult.error("新密码 长度不能少于6位");
        }
        if (password.equals(oldPassword)) {
            return ApiResult.error("新密码，旧密码 不能相同");
        }
//        log.info("密码匹配: {}",this.passwordEncoder.matches(oldPassword,user.getPassword()));
//        log.info("密码: {}   {}",oldPassword,user.getPassword());
        // 2.用户信息不存在/密码不匹配
        if (user == null || user.getId() == 0 || !this.passwordEncoder.matches(oldPassword, user.getPassword())) {
            return ApiResult.error("旧密码 错误");
        }

        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("id", userId);
        // 3.更新用户密码
        this.userMapper.updateByExampleSelective(User.builder()
                .password(this.passwordEncoder.encode(password))
                .build(), example);
        return ApiResult.success("更改成功");
    }

    public ApiResult getUidByUsername(String username) throws SecurityException {
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("username", username);
        User currUser = this.userMapper.selectOneByExample(example);
        if (currUser == null) {
            return ApiResult.error("用户信息 不存在");
        }
        return ApiResult.success(currUser.getId());
    }


    public User getUserByCode(String code) throws SecurityException {
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("code", code);
//        criteria.andEqualTo("userType", userType);
        return this.userMapper.selectOneByExample(example);
    }


}
